<?php

/*
 * CopyRight  : (C)2012-2099 HaoTeam Inc.
 * Document   : MenuService.php
 * Created on : 2020-11-2 10:48:05
 * Author     : Tiger <1192851302@qq.com>
 * Description: This is NOT a freeware, use is subject to license terms.
 *              这即使是一个免费软件,使用时也请遵守许可证条款,得到当时人书面许可.
 *              未经书面许可,不得翻版,翻版必究;版权归属 HaoTeam Inc;
 */

namespace haoteam\service;

use think\facade\Db;

/**
 * 系统菜单管理服务
 * Class MenuService
 * Tiger <1192851302@qq.com> 2020-11-2 10:48:05
 */
class MenuService {

    /**
     * 快速实例化模型
     * @param bool $singleton 是否单例
     * @return static
     */
    public static function instance($singleton = true) {
        $name = static::class;
        if (isset($GLOBALS['model'][$name]) and is_object($GLOBALS['model'][$name]) and $singleton) {
            return $GLOBALS['model'][$name];
        } else {
            $GLOBALS['model'][$name] = new static();
            return $GLOBALS['model'][$name];
        }
    }

    /**
     * 获取可选菜单节点
     * @return array
     * @throws \ReflectionException
     */
    public function getList(): array {
        static $nodes = [];
        if (count($nodes) > 0) {
            return $nodes;
        }
        foreach (NodeService::instance()->getMethods(true) as $node => $method) {
            if ($method['ismenu']) {
                $nodes[] = ['node' => $node, 'title' => $method['title']];
            }
        }
        return $nodes;
    }

    /**
     * 获取系统菜单树数据
     * @return array
     * @throws \ReflectionException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getTree(): array {
        return $this->_buildData(DataExtend::arr2tree(Db::name('admin_menus')->where(['status' => '1'])->order('sort desc,id asc')->select()->toArray()));
    }

    /**
     * 后台主菜单权限过滤
     * @param array $menus 当前菜单列表
     * @return array
     * @throws \ReflectionException
     */
    private function _buildData(array $menus): array {
        $service = AdminService::instance();
        foreach ($menus as $key => &$menu) {
            if (!empty($menu['children'])) {
                $menu['children'] = $this->_buildData($menu['children']);
            }
            if (!empty($menu['children'])) {
                $menu['jump'] = '#';
            } elseif ($menu['jump'] === '#') {
                unset($menus[$key]);
            } elseif (preg_match('|^https?://|i', $menu['jump'])) {
                if (!!$menu['children'] && !$service->check($menu['children'])) {
                    unset($menus[$key]);
                } elseif ($menu['query']) {
                    $menu['jump'] .= (strpos($menu['jump'], '?') === false ? '?' : '&') . $menu['query'];
                }
            } elseif (!!$menu['node'] && !$service->check($menu['node'])) {
                unset($menus[$key]);
            } else {
                $node = join('/', array_slice(explode('/', $menu['jump']), 0, 3));
                $menu['jump'] = $menu['jump'] . ($menu['query'] ? '?' . $menu['query'] : '');
                if (!$service->check($node)) {
                    unset($menus[$key]);
                }
            }
        }
        return $menus;
    }

}
